// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Jobs;
using MQTTnet.Internal;

namespace MQTTnet.Benchmarks;

[SimpleJob(RuntimeMoniker.Net60)]
[MemoryDiagnoser]
public class AsyncLockBenchmark : BaseBenchmark
{
    [Benchmark]
    public async Task Synchronize_100_Tasks()
    {
        const int tasksCount = 100;

        var tasks = new Task[tasksCount];
        var asyncLock = new AsyncLock();
        var globalI = 0;

        for (var i = 0; i < tasksCount; i++)
        {
            tasks[i] = Task.Run(
                async () =>
                {
                    using (await asyncLock.EnterAsync().ConfigureAwait(false))
                    {
                        var localI = globalI;
                        await Task.Delay(5).ConfigureAwait(false); // Increase the chance for wrong data.
                        localI++;
                        globalI = localI;
                    }
                });
        }

        await Task.WhenAll(tasks).ConfigureAwait(false);

        if (globalI != tasksCount)
        {
            throw new InvalidOperationException($"Code is broken ({globalI})!");
        }
    }

    [Benchmark]
    public async Task Wait_100_000_Times()
    {
        var asyncLock = new AsyncLock();

        using var cancellationToken = new CancellationTokenSource();
        for (var i = 0; i < 100000; i++)
        {
            using (await asyncLock.EnterAsync(cancellationToken.Token).ConfigureAwait(false))
            {
            }
        }
    }
}